interface Named {
    name: string;
}

class Person {
    name: string;
}

let p: Named;
// OK, because of structural typing
p = new Person();

interface Named {
    name: string;
}

let x2: Named;
// y's inferred type is { name: string; location: string; }
let y = { name: 'Alice', location: 'Seattle' };
x2 = y;

let x5 = (a: number) => 0;
let y5 = (b: number, s: string) => 0;

y5 = x5; // OK
x5 = y5; // Error




let items = [1, 2, 3];

// Don't force these extra arguments
items.forEach((item, index, array) => console.log(item));

// Should be OK!
items.forEach((item) => console.log(item));



enum EventType { Mouse, Keyboard }

interface Event { timestamp: number; }
interface MouseEvent extends Event { x: number; y: number }
interface KeyEvent extends Event { keyCode: number }

function listenEvent(eventType: EventType, handler: (n: Event) => void) {
    /* ... */
}

// Unsound, but useful and common
listenEvent(EventType.Mouse, (e: MouseEvent) => console.log(e.x + ',' + e.y));

// Undesirable alternatives in presence of soundness
listenEvent(EventType.Mouse, (e: Event) => console.log((<MouseEvent>e).x + ',' + (<MouseEvent>e).y));
listenEvent(EventType.Mouse, <(e: Event) => void>((e: MouseEvent) => console.log(e.x + ',' + e.y)));

// Still disallowed (clear error). Type safety enforced for wholly incompatible types
listenEvent(EventType.Mouse, (e: number) => console.log(e));




function invokeLater(args: any[], callback: (...args: any[]) => void) {
    /* ... Invoke callback with 'args' ... */
}

// Unsound - invokeLater "might" provide any number of arguments
invokeLater([1, 2], (x, y) => console.log(x + ', ' + y));

// Confusing (x and y are actually required) and undiscoverable
invokeLater([1, 2], (x?, y?) => console.log(x + ', ' + y));


enum Status { Ready, Waiting };
enum Color { Red, Blue, Green };

let status8 = Status.Ready;
status8 = Color.Green;  // Error


interface Empty<T> {
}
let x: Empty<number> = 1;
let yy: Empty<string> = "hello";

yy = x;  // OK, because y matches structure of x

interface T {
    n:string;
} 
interface U {
    m:string
} 
let identity = function<T>(x: T): T {
    // ...
    return x;
}

let reverse = function<U>(y: U): U {
    // ...
    return y;
}

identity = reverse;  // OK, because (x: any) => any matches (y: any) => any